package render;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.Vector;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

import entity.Cube;
import entity.Player;

import tutorialFiles.Block.BlockType;
import world.Block;
import world.BlockElement;
import world.Chunk;

public class RenderChunk {
/*
 * Chunk rendering class
 * 
 * 1.Shaders loading and shaders are barrowed from the tutorial on programming
 * a quad with vbos by  http://lwjgl.org/wiki/index.php?title=The_Quad_colored#4_components_instead_of_3.3F
	Mathias Verboven (moci)
   2.http://lwjgl.org/wiki/index.php?title=
   The_Quad_with_Projection,_View_and_Model_matrices#Projection_matrix
 */
	
	private Vector<Chunk> renderList = new Vector<Chunk>();
	private Vector<Cube> cubeList = new Vector<Cube>();
	private Chunk[] chunk = new Chunk[3];
	
	private float size =0.5f;
	private boolean updateable =false;
	
	DisplayMode displayMode;
	
	private Player player = new Player("player",1.0f,1.0f,1.0f);
	private float zNear= 0.1f;
	private float zFar=100f;
	private Vector<Float> colors= new Vector<Float>();
	private Vector<Float> vertexPos= new Vector<Float>();
	private Vector<Byte> indices= new Vector<Byte>();
	
	private int indicesCount;
	private int worldSize;
	private int chunkSize=Chunk.getBlocksPerCubicChunk()
			*Chunk.getBlocksPerCubicChunk()*Chunk.getBlocksPerCubicChunk();
	
	private int VBOVertex;
	private int VBOColor;
	private int VBOIndices;
	private int vertexArrayObject;
	
	//the following variables are used with the shaders
	//barrowed from 1.
	private int vsId = 0;
	private int fsId = 0;
	private int pId =0;
	
	private int projectionMatrixLocation=0;
	private int viewMatrixLocation =0;
	private int modelMatrixLocation =0;
	
	private int width = 800;
	private int height = 600;
	
	private Matrix4f projectionMatrix =null;
	private Matrix4f viewMatrix =null;
	private Matrix4f modelMatrix =null;
	
	private Vector3f modelPos =null;
	private Vector3f modelAngle = null;
	private Vector3f modelScale = null;
	private Vector3f cameraPos = null;
	private FloatBuffer matrix44Buffer = null;

	private final int vertexComponentLength =3;
	private final int pointsPerTriangle=3;
	private final int pointsPerFace=4;
	private final int trianglesPerFace=2;
	private final int factorsPerVertex=3;
	private final int triangleFloatSize=factorsPerVertex*pointsPerTriangle;
	private int colorsPerBlock =3;
	
	
	private Vector<ChunkRenderData> chunkData = new Vector<ChunkRenderData>();
	
	//this method is barrowed from 1 to setup the shaders
	private void setupShaders() {
		int errorCheckValue = GL11.glGetError();
		
		// Load the vertex shader
		vsId = this.loadShader("src/render/vertex.glsl", GL20.GL_VERTEX_SHADER);
		// Load the fragment shader
		fsId = this.loadShader("src/render/fragment.glsl", GL20.GL_FRAGMENT_SHADER);
		
		// Create a new shader program that links both shaders
		// Create a new shader program that links both shaders
				pId = GL20.glCreateProgram();
				GL20.glAttachShader(pId, vsId);
				GL20.glAttachShader(pId, fsId);
				

				// Position information will be attribute 0
				GL20.glBindAttribLocation(pId, 0, "in_Position");
				// Color information will be attribute 1
				GL20.glBindAttribLocation(pId, 1, "in_Color");
				
				GL20.glLinkProgram(pId);
				
				// Get matrices uniform locations
				projectionMatrixLocation = GL20.glGetUniformLocation(pId, "projectionMatrix");
				viewMatrixLocation = GL20.glGetUniformLocation(pId, "viewMatrix");
				modelMatrixLocation = GL20.glGetUniformLocation(pId, "modelMatrix");
				
				GL20.glValidateProgram(pId);
				
				
			}
	//this method is barrowed from 1 to load the shaders
	public int loadShader(String filename, int type) {
		StringBuilder shaderSource = new StringBuilder();
		int shaderID = 0;
		
		try {
			BufferedReader reader = new BufferedReader(new FileReader(filename));
			String line;
			while ((line = reader.readLine()) != null) {
				shaderSource.append(line).append("\n");
			}
			reader.close();
		} catch (IOException e) {
			System.err.println("Could not read file.");
			e.printStackTrace();
			System.exit(-1);
		}
		
		shaderID = GL20.glCreateShader(type);
		GL20.glShaderSource(shaderID, shaderSource);
		GL20.glCompileShader(shaderID);
		
		return shaderID;
	}
	
	private void setupMatrices(){
		// based on the tutorial for projection at 2.
		// Setup projection matrix
				projectionMatrix = new Matrix4f();
				float fieldOfView = 60f;
				float aspectRatio = (float)width / (float)height;
				float near_plane = 0.1f;
				float far_plane = 100f;
				
				float y_scale = this.coTangent(this.degreesToRadians(fieldOfView / 2f));
				float x_scale = y_scale / aspectRatio;
				float frustum_length = far_plane - near_plane;
				
				projectionMatrix.m00 = x_scale;
				projectionMatrix.m11 = y_scale;
				projectionMatrix.m22 = -((far_plane + near_plane) / frustum_length);
				projectionMatrix.m23 = -1;
				projectionMatrix.m32 = -((2 * near_plane * far_plane) / frustum_length);
				
				// Setup view matrix
				viewMatrix = new Matrix4f();
				
				// Setup model matrix
				modelMatrix = new Matrix4f();
				
				// Create a FloatBuffer with the proper size to store our matrices later
				matrix44Buffer = BufferUtils.createFloatBuffer(16);
	}
	
	private float coTangent(float angle)
	{
	float coTan =1f;
	coTan /= (float) Math.tan(angle);
	return coTan;
	}
	
	private float degreesToRadians(float degrees)
	{
		float rad  =degrees;
		rad*=(float)(Math.PI/180d);
		
		return rad;
	}
	
	private void updateMatrices()
	{
		//-- Input processing
		//float rotationDelta = 15f;
		//float scaleDelta = 0.1f;
		//float posDelta = 0.1f;
		//Vector3f scaleAddResolution = new Vector3f(scaleDelta, scaleDelta, scaleDelta);
		//Vector3f scaleMinusResolution = new Vector3f(-scaleDelta, -scaleDelta, 
			//	-scaleDelta);
		
		//System.err.print("ModelPos: "+modelPos.toString());
		
		//-- Update matrices
		// Reset view and model matrices
		viewMatrix = new Matrix4f();
		modelMatrix = new Matrix4f();
		
		
		modelAngle.x=player.getRotX();
		modelAngle.y=player.getRotY();
		modelAngle.z=player.getRotZ();
		
		modelPos.x=player.getPosX();
		modelPos.y=player.getPosY();
		modelPos.z=player.getPosZ();
		// Translate camera
		//Matrix4f.translate(cameraPos, viewMatrix, viewMatrix);
		
		// Scale, translate and rotate model
		//Matrix4f.scale(modelScale, modelMatrix, modelMatrix);
		Matrix4f.translate(modelPos, modelMatrix, modelMatrix);
		
		Matrix4f.rotate(this.degreesToRadians(modelAngle.z), new Vector3f(0, 0, 1), 
				modelMatrix, modelMatrix);
		Matrix4f.rotate(this.degreesToRadians(modelAngle.y), new Vector3f(0, 1, 0), 
				modelMatrix, modelMatrix);
		Matrix4f.rotate(this.degreesToRadians(modelAngle.x), new Vector3f(1, 0, 0), 
				modelMatrix, modelMatrix);
		
		// Upload matrices to the uniform variables
		GL20.glUseProgram(pId);
		
		projectionMatrix.store(matrix44Buffer); matrix44Buffer.flip();
		GL20.glUniformMatrix4(projectionMatrixLocation, false, matrix44Buffer);
		viewMatrix.store(matrix44Buffer); matrix44Buffer.flip();
		GL20.glUniformMatrix4(viewMatrixLocation, false, matrix44Buffer);
		modelMatrix.store(matrix44Buffer); matrix44Buffer.flip();
		GL20.glUniformMatrix4(modelMatrixLocation, false, matrix44Buffer);
		
		GL20.glUseProgram(0);
		
		///this.exitOnGLError("logicCycle");
	}
	
	
	
	
	public void renderVBOWithIndices()
	{
		
		this.updateMatrices();
		//GL11.glLoadIdentity();
		//GL11.glTranslatef(0, 0, 0f);
		//GL11.glRotated(45f, 1.0f, 0.0f, 0.0f);
		
		
		//player.lookAt();
            
		
		//GL11.glPushMatrix();
		  
		GL20.glUseProgram(pId);//use shader program from tutorial at 1.
		//GL11.glPushMatrix();
		
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		
		GL30.glBindVertexArray(vertexArrayObject);
		
		
		
		GL20.glEnableVertexAttribArray(0);
		GL20.glEnableVertexAttribArray(1);
		
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, VBOIndices);
		//GL30.glBindVertexArray(VBOVertex);
		
		
		//GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, chunkSize*24*worldSize);
		
		GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_BYTE, 0);
		
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
		
		GL20.glDisableVertexAttribArray(0);
		GL20.glDisableVertexAttribArray(1);
		GL30.glBindVertexArray(0);
		GL20.glUseProgram(0);
		//GL11.glPopMatrix();
	}
	
	public void createVBOWithIndicesData()
	{
		VBOVertex=GL15.glGenBuffers();
		
		VBOIndices=GL15.glGenBuffers();
		float[] chunks;
		
		
		//float[] chunks 
		
			/*= {
				-0.5f, 0.5f, 0f, 
				
				-0.5f, -0.5f, 0f, 
				
				0.5f, -0.5f, 0f, 
				
				0.5f, 0.5f, 0f, 
				
				};*/
		//int repeat = chunks.length;
		float[] colors ;
		/*
		= {
				1f, 0f, 0f, 
				0f, 1f, 0f, 
				0f, 0f, 1f, 
				1f, 1f, 1f, 
		};
		*/
		byte[] indices;
		/*
		
				= {
				
				0, 1, 2,
				
				2, 3, 0
				
				};
		
		*/
		
		
		renderListToFloatWithIndices();
			
			chunks = new float[vertexPos.size()];
			colors = new float[this.colors.size()];
			indices = new byte[this.indices.size()];
			//System.err.print("chunk length"+vertexPos.size());
			//copy verticy data to a float array
			for(int i=0;i<vertexPos.size();i++)
			{
				chunks[i]= vertexPos.elementAt(i).floatValue();
				
			}
			//copy color data to a float array
			//System.err.println("Vertex size:"+chunks.length);
			
			for(int i=0;i<this.colors.size();i++)
			{
				colors[i]= this.colors.elementAt(i).floatValue();
			}
			//copy indices data to a float array
		//	System.err.print("chunk length"+chunks.length);
			
			
			for(int i=0;i<this.indices.size();i++)
			{
				indices[i]= this.indices.elementAt(i).byteValue();
			}
			
			indicesCount= indices.length;
			
		
		FloatBuffer vertexPosData = BufferUtils.createFloatBuffer(chunks.length);
		
		vertexPosData.put(chunks);
		
		vertexPosData.flip();
		
		
		
		VBOColor=GL15.glGenBuffers();
		FloatBuffer colorData = BufferUtils.createFloatBuffer(colors.length);
		//System.err.println("colors length : "+colors.length);
		
		colorData.put(colors);
		colorData.flip();
		
		ByteBuffer indicesBuffer = BufferUtils.createByteBuffer(indices.length);
		indicesBuffer.put(indices);
		indicesBuffer.flip();
		
		vertexArrayObject=GL30.glGenVertexArrays();
		GL30.glBindVertexArray(vertexArrayObject);
		
		
		
		//bind vbovertex
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOVertex);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertexPosData, GL15.GL_STREAM_DRAW);
		GL20.glVertexAttribPointer(0, 4, GL11.GL_FLOAT, false, 0, 0);//
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		//unbind the array buffer
		
		
		
		//bind VBOColor
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOColor);
		
		
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorData, GL15.GL_STREAM_DRAW);
		
		GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		
		GL30.glBindVertexArray(0);
		
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, VBOIndices);
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STREAM_DRAW);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER,0);
		
		modelPos = new Vector3f(0,0,0);
		modelAngle = new Vector3f(0,0,0);
		modelScale = new Vector3f(1,1,1);
		cameraPos =new Vector3f(0,0,0);
		//setup shaders from the tutorial at 1.
		setupShaders();
		setupMatrices();
	}
	
	
	public void setUpWindow() throws LWJGLException
	{ 
		//try {
		//PixelFormat pixelFormat = new PixelFormat();
		
       /* ContextAttribs contextAtrributes = new ContextAttribs(3,2).withForwardCompatible(true)
        		.withProfileCore(true);
			Display.setFullscreen(false);
			Display.setResizable(true);*/
         
         
         
		Display.setDisplayMode(new DisplayMode(width, height));
         Display.setTitle("Microgenesis Engine");
         Display.create();
        // Display.create(pixelFormat, contextAtrributes);
		
		//} catch (LWJGLException e) {
		//	e.printStackTrace();
		//	System.exit(-1);
		//}
         
         
         
	}
	public void setUpWindowForIndices() throws LWJGLException
	{ 
		try {
		PixelFormat pixelFormat = new PixelFormat();
		
        ContextAttribs contextAtrributes = new ContextAttribs(3,2).withForwardCompatible(true)
        		.withProfileCore(true);
			Display.setFullscreen(false);
			Display.setResizable(true);
         
         
         
		Display.setDisplayMode(new DisplayMode(width, height));
         Display.setTitle("Microgenesis Engine");
         //Display.create();
         Display.create(pixelFormat, contextAtrributes);
		
		} catch (LWJGLException e) {
			e.printStackTrace();
			System.exit(-1);
		}
		GL11.glClearColor(0.0f, 0.1f, 0.0f, 0.0f);
         
         
	}
	public void initVBOOpenGL()
	{
		
		 GL11.glEnable(GL11.GL_TEXTURE_2D);
		 //GL11.glEnable(GL11.GL_)
         GL11.glShadeModel(GL11.GL_SMOOTH);
         
         
         GL11.glClearColor(0.0f, 0.1f, 0.0f, 0.0f); 
         
         GL11.glClearDepth(1.0); 
         GL11.glEnable(GL11.GL_DEPTH_TEST);
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE_MINUS_SRC_ALPHA);
         GL11.glDepthFunc(GL11.GL_LEQUAL);
         
         GL11.glMatrixMode(GL11.GL_PROJECTION); 
         GL11.glLoadIdentity();
         GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);

 		GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
         
         GLU.gluPerspective(
           player.getFov(),
           (float)Display.getWidth()/(float)      Display.getHeight(),
          zNear,
           zFar);

         GL11.glMatrixMode(GL11.GL_MODELVIEW);
         GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
         
         GL11.glEnable(GL11.GL_CULL_FACE);
         GL11.glCullFace(GL11.GL_BACK);
		
		
	}
	
	public void initImmediateOpenGL()
	{
		
		 GL11.glEnable(GL11.GL_TEXTURE_2D);
         GL11.glShadeModel(GL11.GL_SMOOTH);
         GL11.glClearColor(0.0f, 0.1f, 0.0f, 0.0f); 
         GL11.glClearDepth(1.0); 
         GL11.glEnable(GL11.GL_DEPTH_TEST);
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE_MINUS_SRC_ALPHA);
         GL11.glDepthFunc(GL11.GL_LEQUAL);

         GL11.glMatrixMode(GL11.GL_PROJECTION); 
         GL11.glLoadIdentity();

         
         GLU.gluPerspective(
           player.getFov(),
           (float)Display.getWidth()/(float)      Display.getHeight(),
          zNear,
           zFar);

         GL11.glMatrixMode(GL11.GL_MODELVIEW);
         GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
         
         GL11.glEnable(GL11.GL_CULL_FACE);
         GL11.glCullFace(GL11.GL_BACK);
         
		
	}
	
	
	
	
	
	public void renderImediate(float dt)
	{
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		
		GL11.glLoadIdentity();
		GL11.glTranslatef(0, -20.0f, -60f);
		GL11.glRotated(45f, 1.0f, 0.0f, 0.0f);
		
		
		player.lookAt();
            
           
		GL11.glBegin(GL11.GL_QUADS);
		
		//System.err.println("Chunks in renderList"+ renderList.size());
		
		for(int chunkCount=0; chunkCount<renderList.size(); chunkCount++)
		{
			
		//makeImidiateCube(0,0,0,1);
			//System.err.println("Chunk" +chunkCount+ "X:"+renderList.elementAt(chunkCount).getXyz()[0]+ "Y:"+renderList.elementAt(chunkCount).getXyz()[1]
				//	+ "Z:"+renderList.elementAt(chunkCount).getXyz()[2]);
		renderChunk(renderList.elementAt(chunkCount));
		
		}
		
		GL11.glEnd();
		
	}
	
	
	public void setUpChunk()
	{
		
		for (int i=0;i<chunk.length;i++)
		{
		chunk[i]= new Chunk();//initialize new chunk into array
		chunk[i].setUpChunk(BlockElement.Element_Dirt,0,0,0);//setup chunk
		
		
		}
		
	}
	
	public void renderChunk()
	{
	
		for (int i=0;i<chunk.length;i++)
		{
		
		
		
		
		Block[][][] blocks = chunk[i].renderChunk();
		
		for(int l1 = 0; l1< blocks.length; l1 ++){
			
			for (int l2 =0; l2<blocks.length; l2++)
			{
				for (int l3 =0; l3<blocks.length; l3++)
				{
				// initialize each block in the loop.	
					if(blocks[l1][l2][l3].exists())
					{
						float[] rgb = getColorForBlockType(blocks[l1][l2][l3].getElementType());
						
						
						makeImidiateCube(l1,l2,l3,size,rgb[0],rgb[1],rgb[2]);
						
						
					}//render block if it exists
					
				}// end of for loop 3
				
			}// end of for loop 2
			
		}// end of for loop 1
		
		
		}
		
	}
	
	public void renderChunk(Chunk chunk)
	{
	
		
		Block[][][] blocks = chunk.renderChunk();
		
		int exists=0;
		
		for(int l1 = 0; l1< blocks.length; l1 ++){
			
			for (int l2 =0; l2<blocks.length; l2++)
			{
				for (int l3 =0; l3<blocks.length; l3++)
				{
				// initialize each block in the loop.	
					//code to skip rendering blocks which are surrounded
					
					if(blocks[l1][l2][l3].exists())
					{
						exists=0;
						//if x-1 exists
						if(l1-1>0)
						{
							if(blocks[l1-1][l2][l3].exists())
							{
							exists++;
							}
						}
						//if x+1 exists
						if(l1+1<blocks.length)
						{
							if(blocks[l1+1][l2][l3].exists())
							{
								exists++;
							}
						}
						
						
						if(l2+1<blocks.length)
						{
							if(blocks[l1][l2+1][l3].exists())
							{
							exists++;
							}
						}
						
						
						if(l2-1>0)
						{
							if(blocks[l1][l2-1][l3].exists())
							{
							exists++;
							}
						}
						
						//if z +1 exists
						if(l3+1<blocks.length)
						{
							if(blocks[l1][l2][l3+1].exists())
							{
							exists++;
							}
						}
						
						//if z-1 exists
						
						if(l3-1>0)
						{
							if(blocks[l1][l2][l3-1].exists())
							{
							exists++;
							}
						}
						//System.err.println("exist: "+exists);
						
						if(exists<6)
						{
						float[] rgb = getColorForBlockType(blocks[l1][l2][l3].getElementType());
						makeImidiateCube(l1+chunk.getXyz()[0]*Chunk.getBlocksPerCubicChunk(),
								l2+chunk.getXyz()[1]*Chunk.getBlocksPerCubicChunk(),
								l3+chunk.getXyz()[2]*Chunk.getBlocksPerCubicChunk(),
								size,rgb[0],rgb[1],rgb[2]);
						}
					}//render block if it exists
					
				}// end of for loop 3
				
			}// end of for loop 2
			
		}// end of for loop 1
		
		
		
		
	}
	
	public void getColorsForIndicesBlock(BlockElement element,int colorLength)
	{
		float rgbSides[]= new float[3];
		float rpgBottom[]= new float[3];
		float rgbTop[]= new float[3];
		//float[] out = new float[colorLength];
		//int counter=0;
		
		
		if(element.GetElementID()==BlockElement.Element_Dirt.GetElementID())
		{
			//System.out.println("r: "+((float)(139f/255f)+" g: "+(float)(69f/255f)+" b: "+(float)(19f/255f)));
			//rgb[0]=139f/255f;
			rgbSides[0]=90f/255f;
			rgbSides[1]=50f/255f;
			rgbSides[2]=19f/255f;
			
			rpgBottom[0]=90f/255f;
			rpgBottom[1]=50f/255f;
			rpgBottom[2]=19f/255f;
			
			rgbTop[0]=90f/255f;
			rgbTop[1]=50f/255f;
			rgbTop[2]=19f/255f;
			
		}
		
		if(element.GetElementID()==BlockElement.Element_Grass.GetElementID())
		{
			
			//double grassColor =10*Math.random();
			//rgb[0]=106f/255f;
			
			rgbSides[0]=0f/255f;
			rgbSides[1]=130f/255f;
			rgbSides[2]=10f/255f;
			
			rpgBottom[0]=90f/255f;
			rpgBottom[1]=50f/255f;
			rpgBottom[2]=19f/255f;
			
			rgbTop[0]=0f/255f;
			rgbTop[1]=92f/255f;
			rgbTop[2]=9f/255f;
			
		//	rgb[0]=1f/255f;
			//rgb[1]=142f/255f;
			//rgb[2]=14f/255f;
			
			//System.err.print("grassBlock");
		}
		
		if(element.GetElementID()==BlockElement.Element_Stone.GetElementID())
		{
			rgbSides[0]=183f/255f;
			rgbSides[1]=183f/255f;
			rgbSides[2]=183f/255f;
			
			rpgBottom[0]=183f/255f;
			rpgBottom[1]=183f/255f;
			rpgBottom[2]=183f/255f;
			
			rgbTop[0]=183f/255f;
			rgbTop[1]=183f/255f;
			rgbTop[2]=183f/255f;
			//System.err.print("stoneBlock");
		}
		
		
		
		
	
			colors.add(rgbSides[0]);
		
			colors.add(rgbSides[1]);
			
			colors.add(rgbSides[2]);
		
		

		for(int i=0;i<4;i++)
		{
		colors.add(rgbTop[0]);

		colors.add(rgbTop[1]);

		colors.add(rgbTop[2]);
		}
		for(int i=0;i<3;i++)
		{
			colors.add(rgbSides[0]);
		
			colors.add(rgbSides[1]);
			
			colors.add(rgbSides[2]);
		}
							
			
		}
	
	public void getColorsForBlock(BlockElement element,int colorLength)
	{
		float rgbSides[]= new float[3];
		float rpgBottom[]= new float[3];
		float rgbTop[]= new float[3];
		//float[] out = new float[colorLength];
		//int counter=0;
		
		
		if(element.GetElementID()==BlockElement.Element_Dirt.GetElementID())
		{
			//System.out.println("r: "+((float)(139f/255f)+" g: "+(float)(69f/255f)+" b: "+(float)(19f/255f)));
			//rgb[0]=139f/255f;
			rgbSides[0]=90f/255f;
			rgbSides[1]=50f/255f;
			rgbSides[2]=19f/255f;
			
			rpgBottom[0]=90f/255f;
			rpgBottom[1]=50f/255f;
			rpgBottom[2]=19f/255f;
			
			rgbTop[0]=90f/255f;
			rgbTop[1]=50f/255f;
			rgbTop[2]=19f/255f;
			
		}
		
		if(element.GetElementID()==BlockElement.Element_Grass.GetElementID())
		{
			
			//double grassColor =10*Math.random();
			//rgb[0]=106f/255f;
			
			rgbSides[0]=0f/255f;
			rgbSides[1]=130f/255f;
			rgbSides[2]=10f/255f;
			
			rpgBottom[0]=90f/255f;
			rpgBottom[1]=50f/255f;
			rpgBottom[2]=19f/255f;
			
			rgbTop[0]=0f/255f;
			rgbTop[1]=92f/255f;
			rgbTop[2]=9f/255f;
			
		//	rgb[0]=1f/255f;
			//rgb[1]=142f/255f;
			//rgb[2]=14f/255f;
			
			//System.err.print("grassBlock");
		}
		
		if(element.GetElementID()==BlockElement.Element_Stone.GetElementID())
		{
			rgbSides[0]=183f/255f;
			rgbSides[1]=183f/255f;
			rgbSides[2]=183f/255f;
			
			rpgBottom[0]=183f/255f;
			rpgBottom[1]=183f/255f;
			rpgBottom[2]=183f/255f;
			
			rgbTop[0]=183f/255f;
			rgbTop[1]=183f/255f;
			rgbTop[2]=183f/255f;
			//System.err.print("stoneBlock");
		}
		
		
		for(int i=0;i<2;i++)
		{
			colors.add(rgbSides[0]);
		
			colors.add(rgbSides[1]);
			
			colors.add(rgbSides[2]);
			
		}
		

		for(int i=0;i<6;i++)
		{
		colors.add(rgbTop[0]);

		colors.add(rgbTop[1]);

		colors.add(rgbTop[2]);
		
		}
		
						
						
		for(int i=0;i<4;i++)
		{
		colors.add(rgbTop[0]);

		colors.add(rgbTop[1]);

		colors.add(rgbTop[2]);
		
		}
						
						for(int i=0;i<4;i++)
						{
						colors.add(rgbTop[0]);

						colors.add(rgbTop[1]);

						colors.add(rgbTop[2]);
						
						}
						
						for(int i=0;i<4;i++)
						{
							colors.add(rgbTop[0]);

							colors.add(rgbTop[1]);

							colors.add(rgbTop[2]);
							
						}
						
						
						for(int i=0;i<4;i++)
						{
							colors.add(rgbSides[0]);
						
							colors.add(rgbSides[1]);
							
							colors.add(rgbSides[2]);
							
						}
						
						
		}
			

	public float[] getColorForBlockType(BlockElement element)
	{
		float[] rgb ={1,1,1};//return white if the block was not one of the types specified
		
		//System.err.println("BlockElement: "+element);
		//System.err.println("Block Element Id: "+element.GetElementID());
		//System.err.println("Grass Element Id: "+BlockElement.Element_Dirt.GetElementID());
		if(element.GetElementID()==BlockElement.Element_Dirt.GetElementID())
		{
			//System.out.println("r: "+((float)(139f/255f)+" g: "+(float)(69f/255f)+" b: "+(float)(19f/255f)));
			//rgb[0]=139f/255f;
			rgb[0]=90f/255f;
			
			//rgb[1]=69f/255f;
			rgb[1]=50f/255f;
			rgb[2]=19f/255f;
			
			//rgb[2]=10f/255f;
			
			//rgb[0]=0.5f;
			//rgb[1]=0.35f;
			//rgb[2]=0.05f;
			
		//	System.err.println("dirtBlock");
		}
		
		if(element.GetElementID()==BlockElement.Element_Grass.GetElementID())
		{
			
			//double grassColor =10*Math.random();
			//rgb[0]=106f/255f;
			
			rgb[0]=0f/255f;
			rgb[1]=168f/255f;
			rgb[2]=82f/255f;
			
		//	rgb[0]=1f/255f;
			//rgb[1]=142f/255f;
			//rgb[2]=14f/255f;
			
			//System.err.print("grassBlock");
		}
		
		if(element.GetElementID()==BlockElement.Element_Stone.GetElementID())
		{
			rgb[0]=183f/255f;
			rgb[1]=183f/255f;
			rgb[2]=183f/255f;
					
			//System.err.print("stoneBlock");
		}
		
		
		return rgb;
	}
	public void makeImidiateCube(float x, float y, float z,float size,float r,float g,float b)
	{
		//side one
		//GL11.glColor3f(0.0f, 1.0f, 0.0f);
		GL11.glColor4f(r, g, b, 1f);
		
		GL11.glVertex3d(x+size, y+size, z-size);
		//GL11.glColor4f(0.0f, 0.5f, 0.0f, 1f);
		GL11.glVertex3d(x-size, y+size, z-size);
		GL11.glVertex3d(x-size, y+size, z+size);
		GL11.glVertex3d(x+size, y+size, z+size);
		
		//side two
		//GL11.glColor3f(0.2f, 0.8f, 0.2f);
		GL11.glColor4f(r, g, b, 1f);
		GL11.glVertex3d(x+size, y-size, z+size);
		GL11.glVertex3d(x-size, y-size, z+size);
		GL11.glVertex3d(x-size, y-size, z-size);
		GL11.glVertex3d(x+size, y-size, z-size);
		
		//side three
		GL11.glColor4f(r, g, b, 1f);
		
		GL11.glVertex3d(x+size, y+size, z+size);
		GL11.glVertex3d(x-size, y+size, z+size);
		GL11.glVertex3d(x-size, y-size, z+size);
		GL11.glVertex3d(x+size, y-size, z+size);
		

		//side four
		GL11.glColor4f(r, g, b, 1f);
		GL11.glVertex3d(x+size, y-size, z-size);
		GL11.glVertex3d(x-size, y-size, z-size);
		GL11.glVertex3d(x-size, y+size, z-size);
		GL11.glVertex3d(x+size, y+size, z-size);
		//side five
		GL11.glColor4f(r, g, b, 1f);
		GL11.glVertex3d(x-size, y+size, z+size);
		GL11.glVertex3d(x-size, y+size, z-size);
		GL11.glVertex3d(x-size, y-size, z-size);
		GL11.glVertex3d(x-size, y-size, z+size);
		
		
		
				//side six
				GL11.glColor4f(r, g, b, 1f);
				GL11.glVertex3d(x+size, y+size, z-size);
				GL11.glVertex3d(x+size, y+size, z+size);
				GL11.glVertex3d(x+size, y-size, z+size);
				GL11.glVertex3d(x+size, y-size, z-size);
		
		
		
		
	}
	/**
	 * @return the renderList
	 */
	
	public void clear()
	{
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		
	}
	
	public void transformations()
	{
		GL11.glLoadIdentity();
		//GL11.glTranslatef(0, 0, -60f);
		//GL11.glRotated(45f, 1.0f, 0.0f, 0.0f);
		
		
		player.lookAt();
		
	}
	public void popMatrix()
	{
		GL11.glPopMatrix();
	}
	
	public void renderVBO()
	{
		clear();
		
		GL11.glPushMatrix();
            
		
		transformations();
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOVertex);
		
		GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOColor);
		
		GL11.glColorPointer(3, GL11.GL_FLOAT, 0, 0L);
		
		
		//GL11.glDrawArrays(GL11.GL_POLYGON_OFFSET_FILL, 0, chunkSize*24*worldSize);
		//GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, chunkSize*24*worldSize);
		//GL11.glDrawArrays(GL11.GL_LINE_STRIP, 0, chunkSize*24*worldSize);
		
		
		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, chunkSize*24*worldSize);
		
		popMatrix();
		
	}
	
	
	
	public void createVBOData()
	{
		VBOVertex=GL15.glGenBuffers();;
		VBOColor=GL15.glGenBuffers();
		
		
		
		
		float[] chunks;
		//int repeat = chunks.length;
		float[] colors;
		//System.err.println("Chunks in render list: "+renderList.size());
		
		
		
		
			renderListToFloat();
			renderCubes();
			
			chunks = new float[vertexPos.size()];
			colors = new float[this.colors.size()];
			//System.err.print("chunk length"+vertexPos.size());
			
			for(int i=0;i<vertexPos.size();i++)
			{
				chunks[i]= vertexPos.elementAt(i).floatValue();
				//System.err.println("Vertex pos "+i+" data: "+vertexPos.elementAt(i).floatValue());
			}
			//System.err.println("Vertex size:"+chunks.length);
			
			for(int i=0;i<this.colors.size();i++)
			{
				colors[i]= this.colors.elementAt(i).floatValue();
			}
			
		//	System.err.print("chunk length"+chunks.length);
			
			
			
			
		
		FloatBuffer vertexPosData = BufferUtils.createFloatBuffer(chunks.length);
		
		vertexPosData.put(chunks);
		
		vertexPosData.flip();
		
		FloatBuffer colorData = BufferUtils.createFloatBuffer(colors.length);
		
		colorData.put(colors);
		colorData.flip();
		
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOVertex);//bind vbovertex
		
		if(updateable)
		{
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertexPosData, GL15.GL_STREAM_DRAW);
		}
		else
		{
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertexPosData, GL15.GL_STATIC_DRAW);//put vertex data
		}
		
		GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);//
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOColor);//bind VBOColor
		
		if(updateable)
		{
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorData, GL15.GL_STREAM_DRAW);
		}else
		{
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorData, GL15.GL_STATIC_DRAW);//put color data
		}
		
		GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		
		
		
	}
	
	
	
	public void renderListToFloat()
	{
		
		
		//System.err.println("RenderList size:"+renderList.size());
		//System.err.println("Existing blocks: "+renderList.lastElement().getNumberOfExistingBlocks());
			for(int chunkCount=0; chunkCount<renderList.size(); chunkCount++)
			{
				 
				chunkToFloat(renderList.elementAt(chunkCount));
				
				
			}
			renderList.removeAllElements();
		
	}
	
	
	
	public void destroyOpenGlWithIndices()
	{
		//Meomory management barrowed from 1.
		
		//
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
		//
		//GL15.glDeleteBuffers(VBOIndices);
		//
		// Delete the shaders
				GL20.glUseProgram(0);
				GL20.glDetachShader(pId, vsId);
				GL20.glDetachShader(pId, fsId);
				
				GL20.glDeleteShader(vsId);
				GL20.glDeleteShader(fsId);
				GL20.glDeleteProgram(pId);
				
				// Select the VAO
				GL30.glBindVertexArray(vertexArrayObject);
				
				// Disable the VBO index from the VAO attributes list
				GL20.glDisableVertexAttribArray(0);
				GL20.glDisableVertexAttribArray(1);
				
				// Delete the vertex VBO
				GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
				GL15.glDeleteBuffers(VBOIndices);
				
				// Delete the color VBO
				GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
				GL15.glDeleteBuffers(VBOColor);
				
				// Delete the index VBO
				GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
				GL15.glDeleteBuffers(VBOVertex);
				
				// Delete the VAO
				GL30.glBindVertexArray(0);
				GL30.glDeleteVertexArrays(vertexArrayObject);
				
				Display.destroy();
	}
	public void renderListToFloatWithIndices()
	{
		
		for(int chunkCount=0; chunkCount<renderList.size(); chunkCount++)
		{
			 
			chunkToFloatVectorForIndiceses(renderList.elementAt(chunkCount));
			
			
		}
		renderList.removeAllElements();
		
		
	}
	
	public void updateVBO()
	{
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBOVertex);
		
		renderListToFloat();
		
		float[] vertUpdate;
		float[] colorUpdate;
		
	}
	
	public void chunkToFloat(Chunk chunk)
	{
		/*
		 * take an chunk and generate an array of floats from all the blocks in the chunk.
		 */
		
		
	Block[][][] blocks = chunk.renderChunk();
	
		//float[] out;
		//Vector<Float> outV = new Vector<Float>();
		//assume that float will be of maximum size of 72 per block and
		//that there will be blocks.length^3 blocks
		
		//int itterator=0;
	//System.err.println("Existing blocks: "+chunk.getNumberOfExistingBlocks());
		int exists=0;
		//boolean[] visibleSides= new boolean[6];
		
		
		//System.err.println("Blocks total: "+16*16*16);
		int blocksIgnored=0;
		boolean[] sideVisibleList = new boolean[6];
		for(int i=0;i<sideVisibleList.length;i++)
		{
			sideVisibleList[i]=true;
		}
		for(int l1 = 0; l1< blocks.length; l1 ++){
			
			for (int l2 =0; l2<blocks.length; l2++)
			{
				for (int l3 =0; l3<blocks.length; l3++)
				{
				// initialize each block in the loop.	
					//code to skip rendering blocks which are surrounded
					//System.err.println("Existing blocks: "+chunk.getNumberOfExistingBlocks());
					
					if(blocks[l1][l2][l3].exists())
					{
						//System.err.println("Block x: "+l1+" y: "+l2+" z: "+l3+" exists");
						exists=0;
						//if x-1 exists
						if(l1-1>0)
						{
							if(blocks[l1-1][l2][l3].exists())
							{
							exists++;
							sideVisibleList[3]=false;
							}
							else
							{
							sideVisibleList[3]=true;	
							}
						}
						else
						{
							sideVisibleList[3]=true;
						}
						//if x+1 exists
						if(l1+1<blocks.length)
						{
							if(blocks[l1+1][l2][l3].exists())
							{
								exists++;
								sideVisibleList[2]=false;
								//
							}
							else
							{
								sideVisibleList[2]=true;
							}
						}
						else
						{
							sideVisibleList[2]=true;
						}
						
						
						if(l2+1<blocks.length)
						{
							if(blocks[l1][l2+1][l3].exists())
							{
							exists++;
							sideVisibleList[4]=false;
							}
							else
							{
								sideVisibleList[4]=true;
							}
						}
						
						
						if(l2-1>0)
						{
							if(blocks[l1][l2-1][l3].exists())
							{
							exists++;
							sideVisibleList[5]=false;
							}
							else
							{
								sideVisibleList[5]=true;	
							}
						}
						else
						{
							sideVisibleList[5]=true;
						}
						//if z +1 exists
						if(l3+1<blocks.length)
						{
							if(blocks[l1][l2][l3+1].exists())
							{
							exists++;
							sideVisibleList[0]=false;
							}
							else
							{
								sideVisibleList[0]=true;
							}
						}
						else
						{
							sideVisibleList[0]=true;
						}
						//if z-1 exists
						
						if(l3-1>0)
						{
							if(blocks[l1][l2][l3-1].exists())
							{
							exists++;
							sideVisibleList[1]=false;
							}
							else
							{
								sideVisibleList[1]=true;
							}
						}
						else
						{
							sideVisibleList[1]=true;
						}
						//System.err.println("exist: "+exists);
						
						
						if(exists<6)
						{
							float tempColors[]=getColorForBlockType(blocks[l1][l2][l3].getElementType());
							
							
							
							cube8pointWith6face(l1+chunk.getXyz()[0]*Chunk.getBlocksPerCubicChunk(),
									l2+chunk.getXyz()[1]*Chunk.getBlocksPerCubicChunk(),
									l3+chunk.getXyz()[2]*Chunk.getBlocksPerCubicChunk(),tempColors[0],tempColors[1],tempColors[2],size,sideVisibleList);
							
							/*float temp[];
							//turn the cube into points
							
								temp=makeWholeCube(l1+chunk.getXyz()[0]*Chunk.getBlocksPerCubicChunk(),
									l2+chunk.getXyz()[1]*Chunk.getBlocksPerCubicChunk(),
									l3+chunk.getXyz()[2]*Chunk.getBlocksPerCubicChunk(),size);
								
								for(int i=0;i<temp.length;i++)
								{
									vertexPos.add(temp[i]);
								}*/
								
								
							/*
							
							*/
							//System.err.println("vertexs: "+temp.length);
							//System.err.println("colors: "+tempColors.length);
							//copy temp into out array
							//System.err.println("temp length :" +temp.length);
							
							//System.err.println("vertex "+temp.length);
							//getColorsForBlock(blocks[l1][l2][l3].getElementType(),temp.length);
							
							/*for(int x=0;x<allColors.length;x++)
							{
								
								colors.add(allColors[x]);
								
							} */
							
						}
						
					}//render block if it exists
					
				}// end of for loop 3
				
			}// end of for loop 2
			
		}// end of for loop 1
		//Float[] temp= new Float[outV.size()];
		//System.err.println("totalBlocksIgnored: "+blocksIgnored);
	}
	public void chunkToFloatVectorForIndiceses(Chunk chunk)
	{
		/*
		 * take an chunk and generate an array of floats from all the blocks in the chunk.
		 */
		
		
	Block[][][] blocks = chunk.renderChunk();
	
		//float[] out;
		//Vector<Float> outV = new Vector<Float>();
		//assume that float will be of maximum size of 72 per block and
		//that there will be blocks.length^3 blocks
		
		//int itterator=0;
	//System.err.println("Existing blocks: "+chunk.getNumberOfExistingBlocks());
		int exists=0;
		boolean[] visibleSides= new boolean[6];
		
		for(int l1 = 0; l1< blocks.length; l1 ++){
			
			for (int l2 =0; l2<blocks.length; l2++)
			{
				for (int l3 =0; l3<blocks.length; l3++)
				{
				// initialize each block in the loop.	
					//code to skip rendering blocks which are surrounded
					//System.err.println("Existing blocks: "+chunk.getNumberOfExistingBlocks());
					if(blocks[l1][l2][l3].exists())
					{
						//System.err.println("Block x: "+l1+" y: "+l2+" z: "+l3+" exists");
						exists=0;
						//if x-1 exists
						if(l1-1>0)
						{
							if(blocks[l1-1][l2][l3].exists())
							{
							exists++;
							
							}
						}
						//if x+1 exists
						if(l1+1<blocks.length)
						{
							if(blocks[l1+1][l2][l3].exists())
							{
								exists++;
							}
						}
						
						
						if(l2+1<blocks.length)
						{
							if(blocks[l1][l2+1][l3].exists())
							{
							exists++;
							visibleSides[0]=false;
							}
							else
							{
							visibleSides[0]=true;	
							}
						}
						else
						{
							visibleSides[0]=true;
						}
						
						
						if(l2-1>0)
						{
							if(blocks[l1][l2-1][l3].exists())
							{
							exists++;
							}
						}
						
						//if z +1 exists
						if(l3+1<blocks.length)
						{
							if(blocks[l1][l2][l3+1].exists())
							{
							exists++;
							}
						}
						
						//if z-1 exists
						
						if(l3-1>0)
						{
							if(blocks[l1][l2][l3-1].exists())
							{
							exists++;
							}
						}
						//System.err.println("exist: "+exists);
						
						if(exists<6)
						{
						
							
							//turn the cube into points and put them in the vector for points
							
							makeIndicesesCube(l1+chunk.getXyz()[0]*Chunk.getBlocksPerCubicChunk(),
									l2+chunk.getXyz()[1]*Chunk.getBlocksPerCubicChunk(),
									l3+chunk.getXyz()[2]*Chunk.getBlocksPerCubicChunk(),size);
							
								//generate colors for each cube verticey and put it in the vector
							getColorsForBlock(blocks[l1][l2][l3].getElementType(),3*8);
							//add the cubes indicies to the indices vector
							makeIndices();
							
						}
					}//render block if it exists
					
				}// end of for loop 3
				
			}// end of for loop 2
			
		}// end of for loop 1
		//Float[] temp= new Float[outV.size()];
	}
	public void makeIndices()
	{
		byte size=(byte)indices.size();
		
		byte out[]={
				0, 1, 2,
				2, 3, 0, //2
				3, 2, 6,
				6, 7, 3, //4
				7, 6, 5,
				5, 4, 7, //6
				4, 0, 3,
				3, 7, 4, //8
				0, 1, 5,
				5, 4, 0,//10
				1, 5, 6,
				6, 2, 1 //12
				
		};
		
		for(int i=0;i<out.length;i++)
		{
			byte indice=(byte)(out[i]+size);
			indices.add(indice);
		}
	}
	public void makeIndicesesCube(float x, float y, float z,float size)
	{
		//try making cube with vectors
		float[] out={
				x-size,y-size,	z+size, 1f,
				x+size, y-size, z+size, 1f,
				x+size, y+size, z+size, 1f,
				x-size, y+size, z+size, 1f,
				x-size, y-size, z-size, 1f,
				x+size, y-size, z-size, 1f,
				x+size, y+size, z-size, 1f,
				x-size, y+size, z-size, 1f,
		};
		//put those vertieces into the vector
		for(int i=0;i<out.length;i++)
		{
			
			try {
				vertexPos.add(out[i]);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.err.println("error related to adding a float to vertexPos.");
			}
			
			
		}
	}
	
	public void renderCubes()
	{
		for(int i=0;i< cubeList.size();i++)
		{
			float tempX=cubeList.elementAt(i).getPosX();
			float tempY=cubeList.elementAt(i).getPosY();
			float tempZ=cubeList.elementAt(i).getPosZ();
			float tempR=cubeList.elementAt(i).getColor().x;
			float tempG=cubeList.elementAt(i).getColor().y;
			float tempB=cubeList.elementAt(i).getColor().z;
			float size=0.4f;
			
			cube8pointWith6face(tempX,tempY,tempZ,tempR,tempG,tempB,size);
			
		}
		
		
	}
	
	public void cube8pointWith6face(float x, float y, float z,float r,float g, float b, float size)
	{
		
		//pA 0,1,0 pB 0,1,1 pC 1,1,1 pD 1,1,0 pE 1,0,0 pF 1,0,1 pG 0,0,0 pH 0,0,1
		
		// 0 ,0 ,0 
		//initialize points
		Vertex pntA= new Vertex();
		Vertex pntB= new Vertex();
		Vertex pntC= new Vertex();
		Vertex pntD= new Vertex();
		Vertex pntE= new Vertex();
		Vertex pntF= new Vertex();
		Vertex pntG= new Vertex();
		Vertex pntH= new Vertex();
		
		//define points and colors
		
		pntA.setPos(new Vector3f(x-size,y-size,z+size));
		pntB.setPos(new Vector3f(x+size,y-size,z+size));
		pntC.setPos(new Vector3f(x+size,y+size,z+size));
		pntD.setPos(new Vector3f(x-size,y+size,z+size));
		pntE.setPos(new Vector3f(x+size,y-size,z-size));
		pntF.setPos(new Vector3f(x-size,y-size,z-size));
		pntG.setPos(new Vector3f(x-size,y+size,z-size));
		pntH.setPos(new Vector3f(x+size,y+size,z-size));
		
		float gMod =(float)(0.1* Math.random());
		
		pntA.setColor(new Vector3f(r,g+gMod,b));
		pntB.setColor(new Vector3f(r,g,b));
		pntC.setColor(new Vector3f(r,g+gMod,b));
		pntD.setColor(new Vector3f(r,g,b));
		pntE.setColor(new Vector3f(r,g+gMod,b));
		pntF.setColor(new Vector3f(r,g,b));
		pntG.setColor(new Vector3f(r,g+gMod,b));
		pntH.setColor(new Vector3f(r,g,b));
		
		facePos(pntA.getPos(),pntB.getPos(),pntC.getPos(),pntD.getPos());//define top face
		faceColor(pntA.getColor(),pntB.getColor(),pntC.getColor(),pntD.getColor());
		
		
		facePos(pntE.getPos(),pntF.getPos(),pntG.getPos(),pntH.getPos());//define top face
		faceColor(pntE.getColor(),pntF.getColor(),pntG.getColor(),pntH.getColor());
		
		
		facePos(pntB.getPos(),pntE.getPos(),pntH.getPos(),pntC.getPos());//define top face
		faceColor(pntB.getColor(),pntE.getColor(),pntH.getColor(),pntC.getColor());
		
		facePos(pntF.getPos(),pntA.getPos(),pntD.getPos(),pntG.getPos());//define top face
		faceColor(pntF.getColor(),pntA.getColor(),pntD.getColor(),pntG.getColor());
		
		facePos(pntD.getPos(),pntC.getPos(),pntH.getPos(),pntG.getPos());//define top face
		faceColor(pntD.getColor(),pntC.getColor(),pntH.getColor(),pntG.getColor());
		
		facePos(pntF.getPos(),pntE.getPos(),pntB.getPos(),pntA.getPos());//define top face
		faceColor(pntF.getColor(),pntE.getColor(),pntB.getColor(),pntA.getColor());
		
	}//end 
	

	public void cube8pointWith6face(float x, float y, float z,float r,float g, float b, float size, boolean[] RenderList)
	{
		//
		//pA 0,1,0 pB 0,1,1 pC 1,1,1 pD 1,1,0 pE 1,0,0 pF 1,0,1 pG 0,0,0 pH 0,0,1
		
		// 0 ,0 ,0 
		//initialize points
		Vertex pntA= new Vertex();
		Vertex pntB= new Vertex();
		Vertex pntC= new Vertex();
		Vertex pntD= new Vertex();
		Vertex pntE= new Vertex();
		Vertex pntF= new Vertex();
		Vertex pntG= new Vertex();
		Vertex pntH= new Vertex();
		
		//define points and colors
		
		pntA.setPos(new Vector3f(x-size,y-size,z+size));
		pntB.setPos(new Vector3f(x+size,y-size,z+size));
		pntC.setPos(new Vector3f(x+size,y+size,z+size));
		pntD.setPos(new Vector3f(x-size,y+size,z+size));
		pntE.setPos(new Vector3f(x+size,y-size,z-size));
		pntF.setPos(new Vector3f(x-size,y-size,z-size));
		pntG.setPos(new Vector3f(x-size,y+size,z-size));
		pntH.setPos(new Vector3f(x+size,y+size,z-size));
		
		float gMod =(float)(0.3* Math.random());//add a slightly random modifeier to be able to see the terrain
		
		pntA.setColor(new Vector3f(r,g+gMod,b));
		pntB.setColor(new Vector3f(r,g,b));
		pntC.setColor(new Vector3f(r,g+gMod,b));
		pntD.setColor(new Vector3f(r,g,b));
		pntE.setColor(new Vector3f(r,g+gMod,b));
		pntF.setColor(new Vector3f(r,g,b));
		pntG.setColor(new Vector3f(r,g+gMod,b));
		pntH.setColor(new Vector3f(r,g,b));
		
		try {
			if(RenderList[0])
			{
			facePos(pntA.getPos(),pntB.getPos(),pntC.getPos(),pntD.getPos());//define top face
			faceColor(pntA.getColor(),pntB.getColor(),pntC.getColor(),pntD.getColor());
			}
			
			if(RenderList[1])
			{
			facePos(pntE.getPos(),pntF.getPos(),pntG.getPos(),pntH.getPos());//define top face
			faceColor(pntE.getColor(),pntF.getColor(),pntG.getColor(),pntH.getColor());
			}
			
			if(RenderList[2])
			{
			facePos(pntB.getPos(),pntE.getPos(),pntH.getPos(),pntC.getPos());//define top face
			faceColor(pntB.getColor(),pntE.getColor(),pntH.getColor(),pntC.getColor());
			}
			
			if(RenderList[3])
			{
			facePos(pntF.getPos(),pntA.getPos(),pntD.getPos(),pntG.getPos());//define top face
			faceColor(pntF.getColor(),pntA.getColor(),pntD.getColor(),pntG.getColor());
			}
			
			if(RenderList[4])
			{
			facePos(pntD.getPos(),pntC.getPos(),pntH.getPos(),pntG.getPos());//define top face
			faceColor(pntD.getColor(),pntC.getColor(),pntH.getColor(),pntG.getColor());
			}
			
			if(RenderList[5])
			{
			facePos(pntF.getPos(),pntE.getPos(),pntB.getPos(),pntA.getPos());//define top face
			faceColor(pntF.getColor(),pntE.getColor(),pntB.getColor(),pntA.getColor());
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}//end 
	
	
	
	public void facePos(Vector3f p1,Vector3f p2,Vector3f p3,Vector3f p4)
	{
		//break a face into two triangles and then store them into a single float array
		
		float[] triOne = new float[triangleFloatSize];
		float[] triTwo = new float[triangleFloatSize];
		triOne=faceToTriangleMesh(p1,p2,p3);
		triTwo=faceToTriangleMesh(p1,p3,p4);
		
		for(int i=0;i<triOne.length;i++)
		{
			vertexPos.add(triOne[i]);
		}
		
		for(int i=0;i<triTwo.length;i++)
		{
			vertexPos.add(triTwo[i]);
		}
		
		
		
	}
	public void faceColor(Vector3f p1,Vector3f p2,Vector3f p3,Vector3f p4)
	{
		//break a face into two triangles and then store them into a single float array
		
		float[] triOne;
		float[] triTwo;
		triOne=faceToTriangleMesh(p1,p2,p3);
		triTwo=faceToTriangleMesh(p1,p3,p4);
		
		for(int i=0;i<triOne.length;i++)
		{
			colors.add(triOne[i]);
		}
		
		for(int i=0;i<triTwo.length;i++)
		{
			colors.add(triTwo[i]);
		}
		
		
		
	}
	public float[] faceToTriangleMesh(Vector3f p1,Vector3f p2,Vector3f p3)
	{
		
		float[] out = new float[pointsPerTriangle*factorsPerVertex];
		 int i=0;
		 
		out[i++]=p1.x;
		out[i++]=p1.y;
		out[i++]=p1.z;
		
		out[i++]=p2.x;
		out[i++]=p2.y;
		out[i++]=p2.z;
		
		out[i++]=p3.x;
		out[i++]=p3.y;
		out[i++]=p3.z;
		//
		
		
		
		return out;
	}
	public float[] triColor(Vector3f p1,Vector3f p2,Vector3f p3)
	{
		
		float[] out = new float[vertexComponentLength*pointsPerFace];
		
		int i=0;
		
		out[i++]=p1.getX();
		out[i++]=p1.getY();
		out[i++]=p1.getZ();
		
		out[i++]=p2.getX();
		out[i++]=p2.getY();
		out[i++]=p2.getZ();
		
		out[i++]=p3.getX();
		out[i++]=p3.getY();
		out[i++]=p3.getZ();
		
		
		return out;
	}
	public float[] makeWholeCube(float x, float y, float z,float size)
	{
		
		
		
		
		float[] out={
				
				//side one
				
				x+size, y+size, z-size,
				x-size, y+size, z-size,
				x-size, y+size, z+size,
				x+size, y+size, z+size,
				
				//side two
				x+size, y-size, z+size,
				x-size, y-size, z+size,
				x-size, y-size, z-size,
				x+size, y-size, z-size,
				
				//side three
				
				
				x+size, y+size, z+size,
				x-size, y+size, z+size,
				x-size, y-size, z+size,
				x+size, y-size, z+size,
				

				//side four
				
				x+size, y-size, z-size,
				x-size, y-size, z-size,
				x-size, y+size, z-size,
				x+size, y+size, z-size,
				
				//side five
				
				x-size, y+size, z+size,
				x-size, y+size, z-size,
				x-size, y-size, z-size,
				x-size, y-size, z+size,
				
				
				
						//side six
						
				x+size, y+size, z-size,
				x+size, y+size, z+size,
				x+size, y-size, z+size,
				x+size, y-size, z-size,
				
		};
		
		return out;
	}
	public void makeCube(float x, float y, float z,float size,boolean side1,boolean side2,boolean side3,boolean side4,boolean side5,boolean side6)
	{
		
		// if side true add else dont.
		
		
		
		
		
		float[] out={
				x+size, y-size, z+size,
				x-size, y+size, z-size,
				x-size, y+size, z+size,
				x+size, y+size, z+size,
				//side two
				x+size, y-size, z+size,
				x-size, y-size, z+size,
				x-size, y-size, z-size,
				x+size, y-size, z-size,
				
				//side three
				
				
				x+size, y+size, z+size,
				x-size, y+size, z+size,
				x-size, y-size, z+size,
				x+size, y-size, z+size,
				

				//side four
				
				x+size, y-size, z-size,
				x-size, y-size, z-size,
				x-size, y+size, z-size,
				x+size, y+size, z-size,
				
				//side five
				
				x-size, y+size, z+size,
				x-size, y+size, z-size,
				x-size, y-size, z-size,
				x-size, y-size, z+size,
				
				
				
						//side six
						
				x+size, y+size, z-size,
				x+size, y+size, z+size,
				x+size, y-size, z+size,
				x+size, y-size, z-size
				
		};
		int mod=0;//modifier for the place in the array to start from
		
		if(side1)
		{
			
			for(int i =0;i<12;i++)
			{
				vertexPos.add(out[i+mod]);
			}
		}
		mod=mod+12;
		if(side2)
		{
			
			for(int i =0;i<12;i++)
			{
				vertexPos.add(out[i+mod]);
			}
		}
		mod=mod+12;
		if(side3)
		{
			for(int i =0;i<12;i++)
			{
				vertexPos.add(out[i+mod]);
			}
		}
		mod=mod+12;
		if(side4)
		{
			for(int i =0;i<12;i++)
			{
				vertexPos.add(out[i+mod]);
			}
		}
		mod=mod+12;
		if(side5)
		{
			for(int i =0;i<12;i++)
			{
				vertexPos.add(out[i+mod]);
			}
		}
		mod=mod+12;
		if(side6)
		{
			for(int i =0;i<12;i++)
			{
				vertexPos.add(out[i+mod]);
			}
		}
			
	}
	
	
	public float[] makeCubeColors(float r,float g,float b,int colors)
	{
		float[] out = new float[colors];
		int counter=0;
		
			for(int x=0;x<out.length;x++)
			{
				if(counter==0)
				{
					out[x]=r;
				}else
				if(counter==1)
				{
					out[x]=g;
				}else
				if(counter==2)
				{
					out[x]=b;
				}
				
				/*else
				 * if(counter==3)
				{
					out[x]=1.0f;
				}*/
				
				counter++;
				if(counter>2)
				{
					counter=0;
				}
				
			}
				
				
		return out;
	}
	
	public void initOpenGlForDisplayLists()
	{
		 GL11.glEnable(GL11.GL_TEXTURE_2D);
		 //GL11.glEnable(GL11.GL_)
         GL11.glShadeModel(GL11.GL_SMOOTH);
         GL11.glClearColor(0.0f, 0.1f, 0.0f, 0.0f); 
         GL11.glClearDepth(1.0); 
         GL11.glEnable(GL11.GL_DEPTH_TEST);
         GL11.glEnable(GL11.GL_BLEND);
         GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE_MINUS_SRC_ALPHA);
         GL11.glDepthFunc(GL11.GL_LEQUAL);
         
         GL11.glMatrixMode(GL11.GL_PROJECTION); 
         GL11.glLoadIdentity();
         
         
         GLU.gluPerspective(
           player.getFov(),
           (float)Display.getWidth()/(float)      Display.getHeight(),
          zNear,
           zFar);

         GL11.glMatrixMode(GL11.GL_MODELVIEW);
         GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
         
         GL11.glEnable(GL11.GL_CULL_FACE);
         GL11.glCullFace(GL11.GL_BACK);
	}
	
	
	
	
	
	
	
	
	public Vector<Chunk> getRenderList() {
		return renderList;
	}
	/**
	 * @param renderList the renderList to set
	 */
	public void setRenderList(Vector<Chunk> renderList) {
		this.renderList = renderList;
	}
	public Player getPlayer() {
		return player;
	}
	public void setPlayer(Player player) {
		this.player = player;
	}

	/**
	 * @return the worldSize
	 */
	public int getWorldSize() {
		return worldSize;
	}

	/**
	 * @param worldSize the worldSize to set
	 */
	public void setWorldSize(int worldSize) {
		this.worldSize = worldSize;
	}

	/**
	 * @return the chunkSize
	 */
	public int getChunkSize() {
		return chunkSize;
	}

	/**
	 * @param chunkSize the chunkSize to set
	 */
	public void setChunkSize(int chunkSize) {
		this.chunkSize = chunkSize;
	}

	/**
	 * @return the updateable
	 */
	public boolean isUpdateable() {
		return updateable;
	}

	/**
	 * @param updateable the updateable to set
	 */
	public void setUpdateable(boolean updateable) {
		this.updateable = updateable;
	}
	/**
	 * @return the cubeList
	 */
	public Vector<Cube> getCubeList() {
		return cubeList;
	}
	/**
	 * @param cubeList the cubeList to set
	 */
	public void setCubeList(Vector<Cube> cubeList) {
		this.cubeList = cubeList;
	}
	
	
}
